/*
 * Copyright (C) 2001-2011 Jacek Sieka, arnetheduck on gmail point com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef DCPLUSPLUS_DCPP_TRANSFER_H_
#define DCPLUSPLUS_DCPP_TRANSFER_H_

#include "forward.h"
#include "MerkleTree.h"
#include "TimerManager.h"
#include "Util.h"
#include "Segment.h"

class Transfer : private boost::noncopyable
{
	public:
		enum Type
		{
			TYPE_FILE,
			TYPE_FULL_LIST,
			TYPE_PARTIAL_LIST,
			TYPE_TREE,
			TYPE_LAST
		};
		
		static const string names[TYPE_LAST];
		
		static const string USER_LIST_NAME;
		static const string USER_LIST_NAME_BZ;
		
		Transfer(UserConnection& conn, const string& path, const TTHValue& tth);
		virtual ~Transfer() { };
		
		int64_t getPos() const
		{
			return pos;
		}
		
		int64_t getStartPos() const
		{
			return getSegment().getStart();
		}
		
		void resetPos()
		{
			pos = 0;    //http://bazaar.launchpad.net/~dcplusplus-team/dcplusplus/trunk/revision/2153
			actual = 0;
		}
		void addPos(int64_t aBytes, int64_t aActual)
		{
			pos += aBytes;
			actual += aActual;
		}
		
		/** Record a sample for average calculation */
		void tick(uint64_t p_CurrentTick);//[!]IRainman refactoring transfer mechanism
	private:
		enum
		{
			MIN_SAMPLES = SPEED_APPROXIMATION_INTERVAL_S,
			AVG_PERIOD = SPEED_APPROXIMATION_INTERVAL_S * 1000
		};
		void updateRunningAverage(uint64_t tick);//[!]IRainman refactoring transfer mechanism
	public:
		int64_t getRunningAverage() const
		{
			return runningAverage ? runningAverage : getAverageSpeed();
		}

		int64_t getActual() const
		{
			return actual;
		}
		
		int64_t getSize() const
		{
			return getSegment().getSize();
		}
		void setSize(int64_t size)
		{
			segment.setSize(size);
		}
		
		bool getOverlapped() const
		{
			return getSegment().getOverlapped();
		}
		void setOverlapped(bool overlap)
		{
			segment.setOverlapped(overlap);
		}
	private:
		int64_t getAverageSpeed() const; //[!]IRainman refactoring transfer mechanism: use getRunningAverage() function!!
	public:
		
		// [-] IRainman refactoring transfer mechanism
		//int64_t getTotal() const
		//{
		//	return getPos() - getStartPos();
		//}
		
		void setStartPos(int64_t aPos)
		{
			startPos = aPos;
			pos = aPos;
		}
		
		int64_t getSecondsLeft(bool wholeFile = false) const;
		
		void getParams(const UserConnection& aSource, StringMap& params) const;
		//[+]FlylinkDC
		UserPtr getUser();
		const UserPtr getUser() const;
		//[~]FlylinkDC
		const HintedUser getHintedUser() const;
		
		const string& getPath() const
		{
			return path;
		}
		const TTHValue& getTTH() const
		{
			return tth;
		}
		
		UserConnection& getUserConnection()
		{
			return userConnection;
		}
		const UserConnection& getUserConnection() const
		{
			return userConnection;
		}
		
		GETSET(Segment, segment, Segment);
		GETSET(Type, type, Type);
		GETSET(uint64_t, start, Start);
		GETSET(uint64_t, lastTick, LastTick);
	private:
	
		typedef std::pair<uint64_t, const int64_t> Sample;
		typedef deque<Sample> SampleList;
		
		SampleList samples;
		mutable CriticalSection cs;
		
		/** The file being transferred */
		string path;
		/** TTH of the file being transferred */
		TTHValue tth;
		/** Bytes transferred over socket */
		int64_t actual;
		/** Bytes transferred to/from file */
		int64_t pos;
		/** Bytes on last avg update */
		//int64_t last; [-] IRainman refactoring transfer mechanism
		/** Starting position */
		int64_t startPos;
		/** Actual speed */
		int64_t runningAverage;
		
		UserConnection& userConnection;
};

#endif /*TRANSFER_H_*/
